<template>
	<view>
		<picker :disabled="_keys.disabled" :mode="_keys.mode" style="flex: 1;" :value="pickerValue.index" :range="_keys.range" :range-key="_keys.rangeKey"
		 @change="change" :start="_keys.start || ''" :end="_keys.end || ''" :fields="_keys.fields" @cancel="cancel">
			<view class="show-input-box" @click.stop="!_keys.disabled && (classCancel=true)" v-if="_keys.async">
				<y-input style="flex: 1;" :keys="i_keys" :value="pickerValue.value" />
				<i class="formicon" :class="_keys.icon" v-if="_keys.required || !value"></i>
			</view>
			<view class="show-input-box" v-else>
				<y-input style="flex: 1;" :keys="i_keys" :value="pickerValue.value" />
				<i class="formicon" :class="_keys.icon" v-if="_keys.required || !value"></i>
			</view>
		</picker>
		<view class="y-async" v-if="_keys.async && classCancel" @click="cancel">
			<view class="model" @click.stop>
				<view class="btns">
					<text @click="cancel">取消</text>
					<text class="ok" @click="ok">确定</text>
				</view>
				<view class="values">
					<view class="box">
						<text @click="modeIndex = 0" :style="modeIndex == 0?{color:'red'}:{}">中国</text>
						<text v-for="(i,key) in values" :key="key" :style="modeIndex == key+1?{color:'red'}:{}" @click="modeIndex = key+1">{{i._value || "请选择"}}</text>
					</view>
				</view>
				<view class="list">
					<view v-for="(i,key) in range" :key="key" v-show="modeIndex == key">
						<view class="list-item" v-for="(t,index) in i" :key="index" @click="itemClick(key,index,t)" :class="[key,index,values] | itemSelect">
							{{t[_keys.rangeKey]}}
						</view>
					</view>
					<view class="sk-chase-box" v-if="loading">
						<view class="sk-chase">
							<view class="sk-chase-dot" v-for="i in 6" :key="i"></view>
						</view>
					</view>
					<view class="sk-chase-box" v-else-if="!(range[modeIndex] || []).length">
						<view>暂无数据</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import yInput from './y-input.vue'
	import * as request from "../utils/request.js"
	export default {
		name:"yPicker",
		components: {
			yInput
		},
		props: {
			value: '',
			keys: {}
		},
		data() {
			return {
				classCancel: false, //是否显示异步表单
				modeIndex: 0,
				range: [],
				values: [],
				loading: false
			}
		},
		computed: {
			pickerValue() {
				let {
					rangeKey,
					range = [],
					mode,
					valueKey = '',
					async,
					asyncKey
				} = this._keys, {
					value: m_value = ''
				} = this, arr = (m_value + '').split(',');
				//异步组件 数据回显
				if(async && !range.length && this.range.length){
					range = this.range;
				}
				if(async && !range.length){
					let o = {};
					console.error("这里有问题，切换valueKey 后无法获取列表。可以修改为递归获取")
					//当asyncKey === valueKey  可执行以下
					Promise.all([this.get(),...arr.map((x,i)=>{
						o[asyncKey] = x;
						return this.get(o,i+1);
					})]).then(res=>{
						const [{_index,_value}] = this.pickerValue.values;
						if(_index != '' && _value != ''){
							this.$set(this,'values',this.pickerValue.values);
						}
					});
					
					return '';
				}
				const t = (arr, value) => {
					for (let i = 0; i < arr.length; i++) {
						const ri = arr[i];
						if (ri instanceof Object && ri[valueKey] === value) {
							return {
								index: i,
								value: ri[rangeKey]
							};
						} else if (ri == value) {
							return {
								index: i,
								value
							};
						}
					}
					return {
						index: value,
						value
					}
				}
				if (mode === 'selector') {
					return t(range, m_value);
				} else if (mode === 'multiSelector') {
					let value = '',
						index = [],
						values = [];
					for (let u = 0; u < arr.length; u++) {
						const {
							value: _value = '',
							index: _index = -1
						} = t(range[u] || [], arr[u]) || {};
						_index > -1 && index.push(_index);
						value += _value;
						values.push({
							_value,
							_index
						});
					}
					return {
						index,
						value,
						values
					}
				} else {
					return {
						index: m_value,
						value: m_value
					}
				}
			},
			_keys() {
				let {
					mode = '',
						fields = 'day',
						range = [],
						icon = 'form-xiala',
						...keys
				} = this.keys;
				if(this.keys.async){
					mode = "multiSelector"
				}
				switch (mode) {
					case 'selector': //普通选择器
					case 'multiSelector': //多列选择器
					case 'time': //时间选择器
					case 'date': //日期选择器
						break;
					case 'year': //年选择器
						fields = mode;
					case 'month': //月选择器
						fields = mode;
					case 'day': //日选择器
						fields = mode;
						icon = 'form-rili';
						mode = 'date';
						break;
					default:
						mode = Array.isArray(range[0]) ? 'multiSelector' : 'selector';
				}
				return {
					mode,
					fields,
					range,
					icon,
					...keys
				}
			},
			i_keys(){
				return {
					...this._keys,
					disabled: true
				}
			}
		},
		filters: {
			itemSelect([key, index, values]) {
				return (values[key] || {})._index == index ? "item-select" : "";
			}
		},
		methods: {
			//异步 组件
			get(data = {},modeIndex) {
				this.loading = true;
				return this._keys.async && request[this._keys.async](data).then(res => {
					if (res.data.length) {
						this.$set(this.range,modeIndex || this.modeIndex, res.data);
					}
					this.loading = false;
				});
			},
			itemClick(key, index, i) {
				this.values.splice(key, this.values.length);
				this.$set(this.range, this.modeIndex = key + 1, []);
				this.$set(this.values, key, {
					_index: index,
					_value: i[this._keys.rangeKey]
				});
				let o = {};
				o[this._keys.asyncKey] = i[this._keys.asyncValueKey];
				this.get(o);
			},
			ok() {
				this.$set(this._keys,'range',this.range);
				this.change({
					detail: {
						value: this.values.map(x => {
							return x._index;
						})
					}
				});
			},
			//静态 组件
			cancel() {
				this.classCancel = false;
			},
			change(e) {
				this.classCancel = false;
				const fun = this[this._keys.mode];
				const obj = typeof fun === 'function' ? fun(e.detail.value, this._keys) : {};
				this.$emit('change', {...obj,_e:e});
				this.$emit('input', obj.valueKey || e.detail.value);
			},
			selector(e, {
				range,
				rangeKey,
				valueKey
			}) {
				const v = range[e];
				let o = {};
				if (v instanceof Object) {
					o = {
						indexs: [e],
						finalName: v[rangeKey],
						value: [v],
						valueKey: v[valueKey || rangeKey]
					}
				} else {
					o = {
						indexs: [e],
						finalName: v,
						value: [v],
						valueKey: v
					}
				}
				return o;
			},
			multiSelector(e, {
				range,
				rangeKey,
				valueKey
			}) {
				let indexs = e,
					finalName = '',
					value = [],
					_valueKey = [];
				for (let i = 0; i < e.length; i++) {
					const t = (range[i] || [])[e[i]];
					if (t instanceof Object) {
						finalName += t[rangeKey];
						_valueKey.push(t[valueKey || rangeKey]);
					} else {
						finalName += t;
						_valueKey.push(t);
					}
					value.push(t);
				}
				return {
					indexs,
					finalName,
					value,
					valueKey: _valueKey.join(',')
				}
			},
			date(e, {
				range,
				rangeKey,
				valueKey
			}) {
				return {
					finalName: e,
					valueKey: e
				}
			},
			
		}
	}
</script>

<style lang="scss">
	@keyframes bottom-top {
		from {
			transform: translateY(100%);
		}

		to {
			transform: translateY(0);
		}
	}

	.formicon {
		color: inherit;
		font-size: .9em;
		transform: translateY(10%) translateX(-2rpx);
		margin-left: 20rpx;
	}

	.show-input-box {
		display: flex;
		justify-content: flex-end;
		align-items: center;
	}

	.y-async {
		position: fixed;
		z-index: 9999;
		background: rgba(0, 0, 0, .4);
		top: 0;
		bottom: 0;
		left: 0;
		right: 0;

		.model {
			position: absolute;
			bottom: 0;
			left: 0;
			right: 0;
			height: 42.5vh;
			background: #FFFFFF;
			animation: bottom-top 300ms;
			animation-fill-mode: forwards;
			display: flex;
			flex-direction: column;
		}

		.btns {
			display: flex;
			justify-content: space-between;
			padding: 30rpx 20rpx;
			color: #888;
			position: relative;

			&::after {
				content: '';
				position: absolute;
				bottom: 0;
				left: 0;
				right: 0;
				height: 1px;
				background: rgba(0, 0, 0, .3);
				transform: scaleY(.2);
			}

			.ok {
				color: #f00000;
			}
		}

		.values {
			overflow: hidden;
			overflow-x: auto;
			margin: 20rpx;

			.box {
				display: flex;

				text {
					white-space: nowrap;
					padding: 0 10rpx 10rpx;
				}
			}
		}

		.list {
			overflow: hidden;
			overflow-y: auto;
			flex: 1;
			position: relative;

			&-item {
				padding: 16rpx 20rpx;
				text-align: left;
			}

			.item-select {
				color: #f00000;

				&::before {
					content: "√";
				}
			}
		}
	}

	.sk-chase-box {
		display: flex;
		position: absolute;
		bottom: 0;
		left: 0;
		right: 0;
		top: 0;
		z-index: 2;
		justify-content: center;
		align-items: center;
		color: #f00000;
	}

	.sk-chase {
		width: 5vw;
		height: 5vw;
		position: relative;
		animation: sk-chase 2.5s infinite linear both;
	}

	.sk-chase-dot {
		width: 100%;
		height: 100%;
		position: absolute;
		left: 0;
		top: 0;
		animation: sk-chase-dot 2.0s infinite ease-in-out both;
	}

	.sk-chase-dot:before {
		content: '';
		display: block;
		width: 25%;
		height: 25%;
		background-color: #f00000;
		border-radius: 100%;
		animation: sk-chase-dot-before 2.0s infinite ease-in-out both;
	}

	.sk-chase-dot:nth-child(1) {
		animation-delay: -1.1s;
	}

	.sk-chase-dot:nth-child(2) {
		animation-delay: -1.0s;
	}

	.sk-chase-dot:nth-child(3) {
		animation-delay: -0.9s;
	}

	.sk-chase-dot:nth-child(4) {
		animation-delay: -0.8s;
	}

	.sk-chase-dot:nth-child(5) {
		animation-delay: -0.7s;
	}

	.sk-chase-dot:nth-child(6) {
		animation-delay: -0.6s;
	}

	.sk-chase-dot:nth-child(1):before {
		animation-delay: -1.1s;
	}

	.sk-chase-dot:nth-child(2):before {
		animation-delay: -1.0s;
	}

	.sk-chase-dot:nth-child(3):before {
		animation-delay: -0.9s;
	}

	.sk-chase-dot:nth-child(4):before {
		animation-delay: -0.8s;
	}

	.sk-chase-dot:nth-child(5):before {
		animation-delay: -0.7s;
	}

	.sk-chase-dot:nth-child(6):before {
		animation-delay: -0.6s;
	}

	@keyframes sk-chase {
		100% {
			transform: rotate(360deg);
		}
	}

	@keyframes sk-chase-dot {

		80%,
		100% {
			transform: rotate(360deg);
		}
	}

	@keyframes sk-chase-dot-before {
		50% {
			transform: scale(0.4);
		}

		100%,
		0% {
			transform: scale(1.0);
		}
	}
</style>
